/* * Copyright (c) 2011-2012 Lockheed Martin Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.eurekastreams.web.client.ui.pages.activity; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eurekastreams.server.domain.AvatarUrlGenerator; import org.eurekastreams.server.domain.EntityType; import org.eurekastreams.server.domain.Follower.FollowerStatus; import org.eurekastreams.server.domain.Identifiable; import org.eurekastreams.server.domain.Page; import org.eurekastreams.server.domain.PagedSet; import org.eurekastreams.server.domain.stream.ActivityDTO; import org.eurekastreams.server.domain.stream.Stream; import org.eurekastreams.server.domain.stream.StreamFilter; import org.eurekastreams.server.domain.stream.StreamScope; import org.eurekastreams.server.domain.stream.StreamScope.ScopeType; import org.eurekastreams.server.search.modelview.DomainGroupModelView; import org.eurekastreams.server.search.modelview.PersonModelView; import org.eurekastreams.server.search.modelview.PersonModelView.Role; import org.eurekastreams.web.client.events.CustomStreamCreatedEvent; import org.eurekastreams.web.client.events.CustomStreamDeletedEvent; import org.eurekastreams.web.client.events.CustomStreamUpdatedEvent; import org.eurekastreams.web.client.events.EventBus; import org.eurekastreams.web.client.events.HistoryViewsChangedEvent; import org.eurekastreams.web.client.events.MessageStreamAppendEvent; import org.eurekastreams.web.client.events.Observer; import org.eurekastreams.web.client.events.ShowNotificationEvent; import org.eurekastreams.web.client.events.StreamReinitializeRequestEvent; import org.eurekastreams.web.client.events.StreamSearchBeginEvent; import org.eurekastreams.web.client.events.UpdateHistoryEvent; import org.eurekastreams.web.client.events.UpdatedHistoryParametersEvent; import org.eurekastreams.web.client.events.data.AddedFeaturedStreamResponseEvent; import org.eurekastreams.web.client.events.data.GotActivityResponseEvent; import org.eurekastreams.web.client.events.data.GotCurrentUserCustomStreamsResponseEvent; import org.eurekastreams.web.client.events.data.GotCurrentUserStreamBookmarks; import org.eurekastreams.web.client.events.data.GotGroupModelViewInformationResponseEvent; import org.eurekastreams.web.client.events.data.GotPersonFollowerStatusResponseEvent; import org.eurekastreams.web.client.events.data.GotPersonalInformationResponseEvent; import org.eurekastreams.web.client.events.data.GotStreamActivitySubscriptionResponseEvent; import org.eurekastreams.web.client.events.data.GotStreamResponseEvent; import org.eurekastreams.web.client.events.data.InsertedGroupMemberResponseEvent; import org.eurekastreams.web.client.events.data.InsertedPersonFollowerResponseEvent; import org.eurekastreams.web.client.events.data.InsertedRequestForGroupMembershipResponseEvent; import org.eurekastreams.web.client.events.data.PostableStreamScopeChangeEvent; import org.eurekastreams.web.client.events.data.StreamActivitySubscriptionChangedEvent; import org.eurekastreams.web.client.events.data.UpdatedGroupStickyActivityEvent; import org.eurekastreams.web.client.history.CreateUrlRequest; import org.eurekastreams.web.client.jsni.EffectsFacade; import org.eurekastreams.web.client.jsni.WidgetJSNIFacadeImpl; import org.eurekastreams.web.client.model.ActivityModel; import org.eurekastreams.web.client.model.CustomStreamModel; import org.eurekastreams.web.client.model.Deletable; import org.eurekastreams.web.client.model.GadgetModel; import org.eurekastreams.web.client.model.GroupActivitySubscriptionModel; import org.eurekastreams.web.client.model.GroupMembershipRequestModel; import org.eurekastreams.web.client.model.GroupModel; import org.eurekastreams.web.client.model.PersonActivitySubscriptionModel; import org.eurekastreams.web.client.model.PersonalInformationModel; import org.eurekastreams.web.client.model.StreamBookmarksModel; import org.eurekastreams.web.client.model.StreamModel; import org.eurekastreams.web.client.model.requests.AddGadgetToStartPageRequest; import org.eurekastreams.web.client.ui.Session; import org.eurekastreams.web.client.ui.common.SpinnerLabelButton; import org.eurekastreams.web.client.ui.common.avatar.AvatarBadgeManager; import org.eurekastreams.web.client.ui.common.avatar.AvatarLinkPanel; import org.eurekastreams.web.client.ui.common.avatar.AvatarWidget.Size; import org.eurekastreams.web.client.ui.common.dialog.Dialog; import org.eurekastreams.web.client.ui.common.notifier.Notification; import org.eurekastreams.web.client.ui.common.stream.ActivityDetailPanel; import org.eurekastreams.web.client.ui.common.stream.GroupEmailSubscribeOptionsDialogContent; import org.eurekastreams.web.client.ui.common.stream.StreamJsonRequestFactory; import org.eurekastreams.web.client.ui.common.stream.StreamSearchStatusWidget; import org.eurekastreams.web.client.ui.common.stream.StreamToUrlTransformer; import org.eurekastreams.web.client.ui.common.stream.UnseenActivityNotificationPanel; import org.eurekastreams.web.client.ui.common.stream.filters.list.CustomStreamDialogContent; import org.eurekastreams.web.client.ui.common.stream.renderers.ShowRecipient; import org.eurekastreams.web.client.ui.common.stream.renderers.StickyActivityRenderer; import org.eurekastreams.web.client.ui.common.stream.renderers.StreamMessageItemRenderer; import org.eurekastreams.web.client.ui.common.widgets.activity.PostBoxComposite; import org.eurekastreams.web.client.ui.common.widgets.activity.StreamDetailsComposite; import org.eurekastreams.web.client.ui.common.widgets.activity.StreamDetailsComposite.CustomAvatar; import org.eurekastreams.web.client.ui.pages.master.StaticResourceBundle; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Style.Display; import com.google.gwt.event.dom.client.BlurEvent; import com.google.gwt.event.dom.client.BlurHandler; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONObject; import com.google.gwt.resources.client.CssResource; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.History; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; //import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTMLPanel; import com.google.gwt.user.client.ui.Hyperlink; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.UIObject; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.http.client.URL; /** * Activity Page. */ public class ActivityContent extends Composite { /** Text displayed for locked users. */ private static final String LOCKED_USER_TEXT = "This employee has no profile in Eureka Streams. This could be due" + " to an incorrect or outdated link, a change in assignment within the company, or leaving the company."; /** Amount of time to wait after a key is pressed before performing a search. */ private static final int SEARCH_UPDATE_DELAY = 500; /** Amount of time to wait after a key is pressed to update the URL with the search term. */ private static final int SEARCH_URL_UPDATE_DELAY = 2000; /** Binder for building UI. */ private static LocalUiBinder binder = GWT.create(LocalUiBinder.class); /** * CSS resource. */ interface ActivityStyle extends CssResource { /** * Active sort style. * * @return Active sort style */ String activeSort(); /** * Active stream style. * * @return Active stream style. */ String activeStream(); /** * Stream options child. * * @return Stream options child. */ String streamOptionChild(); /** * Delete bookmark. * * @return delete bookmark. */ String deleteBookmark(); /** * Edit custom stream. * * @return edit custom stream. */ String editCustomStream(); /** * The stream name style. * * @return the stream name style. */ String streamName(); /** * Active search style. * * @return active search style. */ String activeSearch(); /** * Current user link style. * * @return current user stream style. */ String currentUserStreamLink(); /** * Small avatar. * * @return small avatar style. */ String smallAvatar(); /** * Current user configure link. * * @return current user configure link. */ String currentUserConfLink(); /** * Message when no bookmarks exist. * * @return message when no bookmarks exist. */ String noBookmarksMessage(); /** @return The stream container panel. */ @ClassName("stream-container-panel") String streamContainerPanel(); } /** * CSS style. */ @UiField ActivityStyle style; /** * Stream details. */ @UiField StreamDetailsComposite streamDetailsComposite; /** * No results panel. */ @UiField DivElement noResults; /** * Search container. */ @UiField DivElement searchContainer; /** * UI element for streams. */ @UiField FlowPanel streamPanel; /** * UI element for bookmarks. */ @UiField FlowPanel bookmarkList; /** * UI element for stream container. */ @UiField HTMLPanel streamContainerPanel; /** * UI element for filters. */ @UiField FlowPanel filterList; /** * UI element for default streams. */ @UiField FlowPanel defaultList; /** * UI element for default streams. */ @UiField FlowPanel errorPanel; /** * UI element for recent sort. */ @UiField Hyperlink recentSort; /** * UI element for popular sort. */ @UiField Hyperlink popularSort; /** * UI element for active sort. */ @UiField Hyperlink activeSort; /** * UI element for activity loading spinner. */ @UiField DivElement activitySpinner; /** * Feed link. */ @UiField Label feedLink; /** * UI element for more spinner. */ @UiField DivElement moreSpinner; /** * UI element for more link. */ @UiField Label moreLink; /** * UI element for adding a bookmark. */ @UiField Label addBookmark; /** * UI element for adding a a stream to the start page. */ @UiField Label addToStartPage; /** * Create Filter. */ @UiField Label createFilter; /** * Subscribe via email. */ @UiField Label subscribeViaEmail; /** * Stream search status widget. */ @UiField StreamSearchStatusWidget streamSearchStatusWidget; /** Link to get contact for emailing to stream. */ //@UiField //Anchor getEmailContactLink; /** * Panel for unseen activity notifications - hidden when viewing a single activity. */ @UiField UnseenActivityNotificationPanel unseenActivityNotificationPanel; /** * Message Renderer. */ StreamMessageItemRenderer renderer = new StreamMessageItemRenderer(ShowRecipient.YES); /** Sticky activity renderer (for groups only). */ private static StickyActivityRenderer stickyActivityRenderer = new StickyActivityRenderer(); /** * Newest activity ID. */ private long longNewestActivityId = 0L; /** * Oldest Activity ID. */ private long longOldestActivityId = 0; /** * Current Request. */ private JSONObject currentRequestObj = null; /** * Search Box. */ @UiField TextBox searchBox; /** * Stream options panel. */ @UiField DivElement streamOptionsPanel; /** * Current stream scope. */ private StreamScope currentStream; /** * Current scope id. */ private long currentScopeId; /** * Current stream display name. */ private String currentDisplayName; /** * Entity for the current stream. Used by the sticky activity logic to determine if any stick/unstick events pertain * to the current view. Would use currentStream, but there is other code that clobbers the entity type if the stream * isn't postable and thus renders currentStream useless for the purpose. */ private Identifiable currentStreamEntity; /** * New activity polling. */ private static final int NEW_ACTIVITY_POLLING_DELAY = 1200000; /** * Custom streams map. */ private final HashMap<Long, StreamNamePanel> customStreamWidgetMap = new HashMap<Long, StreamNamePanel>(); /** * Stream bookmarks map. */ private final HashMap<String, StreamNamePanel> bookmarksWidgetMap = new HashMap<String, StreamNamePanel>(); /** * Currently active stream. */ private Panel currentlyActiveStream = null; /** * Following filter panel. */ private Panel followingFilterPanel = null; /** * Everyone filter panel. */ private Panel everyoneFilterPanel = null; /** * Is subscribed. */ private boolean isSubscribed = false; /** * Post Box. */ @UiField PostBoxComposite postBox; /** * User panel. */ @UiField FlowPanel userPanel; /** * Current sort keyword. */ private String sortKeyword = ""; /** * Single activity mode. */ private boolean singleActivityMode; /** * Bookmarks initially loaded. */ private boolean bookmarksLoaded = false; /** * Bookmarks initially loaded. */ private boolean customStreamsLoaded = false; /** * If the page has ran init. */ private boolean hasInited = false; /** Stream to URL transformer. */ private static final StreamToUrlTransformer STREAM_URL_TRANSFORMER = new StreamToUrlTransformer(); /** * If the entity still needs to be received before making the activity query. * * Explanation: Fetching the activities for a group requires knowing which activity is sticky so it can be excluded * on the query. So the query must be built in loadStream and the DomainGroupModelView must be recieved. * Unfortunately, the event bus notifies inline instead of queuing, thus the call to the GroupModel in loadStream * may fire its event immediately (if the group is in cache), causing the group to be received before loadStream * finishes. So we have to handle two different possible orders. The approach taken is to set this flag and the one * below; whenever they are both reset, the activity query is sent. */ private boolean deferLoadAwaitingEntityReceived; /** * If the activity query isn't done being constructed yet (before making the activity query). See * deferLoadAwaitingEntityReceived. */ private boolean deferLoadAwaitingQueryBuilt; /** Place to put sticky activity. */ @UiField SimplePanel stickyActivityHolder; /** Area containing the sticky activity. */ @UiField DivElement stickyActivityArea; /** Views used to load the current stream. */ List<String> loadedViews = Collections.singletonList("[do not match]"); /** So results for the wrong stream can be detected and ignored. */ private String currentStreamRequest; /** Search term used to load the current stream. */ String loadedSearchTerm = ""; /** Timer to delay progressive search until the user pauses. */ private final Timer searchTimer = new Timer() { @Override public void run() { String searchText = searchBox.getText(); loadStream(Session.getInstance().getUrlViews(), searchText); searchUrlTimer.schedule(SEARCH_URL_UPDATE_DELAY); } }; /** Timer to update the URL with the search term. */ private final Timer searchUrlTimer = new Timer() { @Override public void run() { updateUrlWithSearchTerm(); } }; /** * Default constructor. */ public ActivityContent() { initWidget(binder.createAndBindUi(this)); buildPage(); } /** * Build the page. */ private void buildPage() { addEventHandlers(); addObservers(); setupStreamsAndBookmarks(); moreLink.setVisible(false); streamSearchStatusWidget.setVisible(false); errorPanel.setVisible(false); followingFilterPanel = createPanel("Following", "following", "style/images/customStream.png", null, "", "", false); everyoneFilterPanel = createPanel("Everyone", "everyone", "style/images/customStream.png", null, "", "", false); defaultList.add(followingFilterPanel); defaultList.add(everyoneFilterPanel); final PersonModelView currentPerson = Session.getInstance().getCurrentPerson(); AvatarLinkPanel userAvatar = new AvatarLinkPanel(currentPerson.getEntityType(), currentPerson.getAccountId(), currentPerson.getAvatarId(), Size.Small, currentPerson.getDisplayName()); userPanel.add(userAvatar); FlowPanel userLinkPanel = new FlowPanel(); String nameUrl = Session.getInstance().generateUrl( new CreateUrlRequest(Page.PEOPLE, currentPerson.getAccountId())); Hyperlink name = new Hyperlink(currentPerson.getDisplayName(), nameUrl); name.setTitle(currentPerson.getDisplayName()); name.addStyleName(style.currentUserStreamLink()); name.addStyleName(StaticResourceBundle.INSTANCE.coreCss().ellipsisChild()); userLinkPanel.add(name); String confUrl = Session.getInstance().generateUrl( new CreateUrlRequest(Page.PERSONAL_SETTINGS, currentPerson.getAccountId())); Hyperlink conf = new Hyperlink("Configure My Stream", confUrl); conf.addStyleName(style.currentUserConfLink()); userLinkPanel.add(conf); userPanel.add(userLinkPanel); CustomStreamModel.getInstance().fetch(null, true); StreamBookmarksModel.getInstance().fetch(null, true); moreSpinner.addClassName(StaticResourceBundle.INSTANCE.coreCss().displayNone()); noResults.addClassName(StaticResourceBundle.INSTANCE.coreCss().displayNone()); unseenActivityNotificationPanel.setActive(true); } /** * Got activity. * * @param event * the event. */ private void gotActivity(final GotActivityResponseEvent event) { streamPanel.clear(); unseenActivityNotificationPanel.setActive(false); activitySpinner.addClassName(StaticResourceBundle.INSTANCE.coreCss().displayNone()); if (event.getResponse() != null) { EntityType actorType = event.getResponse().getDestinationStream().getEntityType(); String actorName = event.getResponse().getDestinationStream().getUniqueId(); if (actorType.equals(EntityType.GROUP)) { GroupModel.getInstance().fetch(actorName, false); } else if (actorType.equals(EntityType.PERSON)) { PersonalInformationModel.getInstance().fetch(actorName, false); } } streamPanel.add(new ActivityDetailPanel(event.getResponse(), ShowRecipient.YES)); streamPanel.removeStyleName(StaticResourceBundle.INSTANCE.coreCss().hidden()); } /** * Add events. */ private void addObservers() { final EventBus eventBus = EventBus.getInstance(); eventBus.addObserver(GotActivityResponseEvent.class, new Observer<GotActivityResponseEvent>() { public void update(final GotActivityResponseEvent event) { gotActivity(event); } }); eventBus.addObserver(GotStreamResponseEvent.class, new Observer<GotStreamResponseEvent>() { public void update(final GotStreamResponseEvent event) { // throw out results if for the wrong stream (or we don't want the results) if (currentStreamRequest == null || !currentStreamRequest.equals(event.getRequest())) { return; } final PagedSet<ActivityDTO> activitySet = event.getStream(); if (activitySet.getPagedSet().size() > 0) { longNewestActivityId = activitySet.getPagedSet().get(0).getEntityId(); longOldestActivityId = activitySet.getPagedSet().get(activitySet.getPagedSet().size() - 1) .getEntityId(); } if (StreamJsonRequestFactory.getJSONRequest(event.getJsonRequest()).containsKey("minId")) { for (int i = activitySet.getPagedSet().size(); i > 0; i--) { appendActivity(activitySet.getPagedSet().get(i - 1)); } } else if (StreamJsonRequestFactory.getJSONRequest(event.getJsonRequest()).containsKey("maxId")) { moreSpinner.addClassName(StaticResourceBundle.INSTANCE.coreCss().displayNone()); for (ActivityDTO activity : activitySet.getPagedSet()) { streamPanel.add(renderer.render(activity)); } moreLink.setVisible(activitySet.getTotal() > activitySet.getPagedSet().size()); } else { streamPanel.clear(); unseenActivityNotificationPanel.setActive(true); activitySpinner.addClassName(StaticResourceBundle.INSTANCE.coreCss().displayNone()); streamPanel.removeStyleName(StaticResourceBundle.INSTANCE.coreCss().hidden()); List<ActivityDTO> activities = activitySet.getPagedSet(); for (ActivityDTO activity : activities) { streamPanel.add(renderer.render(activity)); } if (activities.size() == 0) { noResults.removeClassName(StaticResourceBundle.INSTANCE.coreCss().displayNone()); } moreLink.setVisible(activitySet.getTotal() > activities.size()); } if (activitySet.getPagedSet().size() > 0) { noResults.addClassName(StaticResourceBundle.INSTANCE.coreCss().displayNone()); } } }); // users are not initially subscribed for emails when following a person/group, so set the status properly (else // if you were following and unsubscribed, then re-subscribed, the status would be old and wrong) eventBus.addObserver(InsertedPersonFollowerResponseEvent.class, new Observer<InsertedPersonFollowerResponseEvent>() { public void update(final InsertedPersonFollowerResponseEvent ev) { setSubscribeStatus(false); } }); eventBus.addObserver(InsertedGroupMemberResponseEvent.class, new Observer<InsertedGroupMemberResponseEvent>() { public void update(final InsertedGroupMemberResponseEvent ev) { setSubscribeStatus(false); } }); eventBus.addObserver(GotPersonFollowerStatusResponseEvent.class, new Observer<GotPersonFollowerStatusResponseEvent>() { public void update(final GotPersonFollowerStatusResponseEvent event) { subscribeViaEmail.setVisible(event.getResponse().equals(FollowerStatus.FOLLOWING)); } }); eventBus.addObserver(HistoryViewsChangedEvent.class, new Observer<HistoryViewsChangedEvent>() { public void update(final HistoryViewsChangedEvent event) { searchTimer.cancel(); searchUrlTimer.cancel(); handleViewsChanged(event.getViews()); final String searchText = Session.getInstance().getParameterValue("search"); if (!searchBox.getText().equals(searchText)) { searchBox.setText(searchText); } } }); eventBus.addObserver(MessageStreamAppendEvent.class, new Observer<MessageStreamAppendEvent>() { public void update(final MessageStreamAppendEvent event) { longNewestActivityId = event.getMessage().getId(); if (sortKeyword.equals("date")) { appendActivity(event.getMessage()); noResults.addClassName(StaticResourceBundle.INSTANCE.coreCss().displayNone()); } else { recentSort.getElement().dispatchEvent( Document.get().createClickEvent(1, 0, 0, 0, 0, false, false, false, false)); } } }); eventBus.addObserver(CustomStreamCreatedEvent.class, new Observer<CustomStreamCreatedEvent>() { public void update(final CustomStreamCreatedEvent event) { CustomStreamModel.getInstance().fetch(null, true); } }); eventBus.addObserver(CustomStreamDeletedEvent.class, new Observer<CustomStreamDeletedEvent>() { public void update(final CustomStreamDeletedEvent event) { CustomStreamModel.getInstance().fetch(null, true); } }); eventBus.addObserver(CustomStreamUpdatedEvent.class, new Observer<CustomStreamUpdatedEvent>() { public void update(final CustomStreamUpdatedEvent event) { CustomStreamModel.getInstance().fetch(null, true); } }); eventBus.addObserver(StreamReinitializeRequestEvent.class, new Observer<StreamReinitializeRequestEvent>() { public void update(final StreamReinitializeRequestEvent event) { loadStream(Session.getInstance().getUrlViews(), Session.getInstance().getParameterValue("search")); } }); eventBus.addObserver(UpdatedHistoryParametersEvent.class, new Observer<UpdatedHistoryParametersEvent>() { public void update(final UpdatedHistoryParametersEvent event) { searchTimer.cancel(); searchUrlTimer.cancel(); if (!event.getViewChanged()) { handleViewsChanged(Session.getInstance().getUrlViews()); } } }); eventBus.addObserver(AddedFeaturedStreamResponseEvent.class, new Observer<AddedFeaturedStreamResponseEvent>() { public void update(final AddedFeaturedStreamResponseEvent event) { eventBus.notifyObservers(new ShowNotificationEvent(new Notification("Stream has been featured."))); } }); eventBus.addObserver(UpdatedGroupStickyActivityEvent.class, new Observer<UpdatedGroupStickyActivityEvent>() { public void update(final UpdatedGroupStickyActivityEvent ev) { // make sure event applies to the current view (since current view may not even be a group) if (currentStreamEntity != null && currentStreamEntity.getEntityType() == EntityType.GROUP && ev.getGroupId() == currentStreamEntity.getEntityId() && !singleActivityMode) { if (ev.getActivity() == null) { stickyActivityHolder.clear(); UIObject.setVisible(stickyActivityArea, false); } else { stickyActivityHolder.clear(); stickyActivityHolder.add(stickyActivityRenderer.render(ev.getActivity())); UIObject.setVisible(stickyActivityArea, true); } // reload the stream to get prior sticky activities back in it (and a freshly stuck activity out) eventBus.notifyObservers(StreamReinitializeRequestEvent.getEvent()); } } }); addEntityObservers(); } /** * Add entity observers. */ private void addEntityObservers() { EventBus.getInstance().addObserver(GotPersonalInformationResponseEvent.class, new Observer<GotPersonalInformationResponseEvent>() { public void update(final GotPersonalInformationResponseEvent event) { PersonModelView person = event.getResponse(); currentDisplayName = person.getDisplayName(); currentScopeId = person.getStreamId(); if (person.isAccountLocked()) { streamOptionsPanel.getStyle().setDisplay(Display.NONE); currentStream.setScopeType(null); errorPanel.clear(); errorPanel.setVisible(true); activitySpinner.addClassName(StaticResourceBundle.INSTANCE.coreCss().displayNone()); errorPanel.add(new Label("Employee profile not found")); errorPanel.add(new Label(LOCKED_USER_TEXT)); streamPanel.removeStyleName(StaticResourceBundle.INSTANCE.coreCss().hidden()); streamDetailsComposite.setVisible(false); currentStream.setScopeType(null); // block display of activities currentStreamRequest = null; streamPanel.clear(); unseenActivityNotificationPanel.setActive(false); activitySpinner.addClassName(StaticResourceBundle.INSTANCE.coreCss().displayNone()); streamPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().hidden()); noResults.addClassName(StaticResourceBundle.INSTANCE.coreCss().displayNone()); moreLink.setVisible(false); } else { currentStream.setDisplayName(person.getDisplayName()); streamDetailsComposite.setVisible(true); } if (!person.isStreamPostable() && !person.getAccountId().equals( Session.getInstance().getCurrentPerson().getAccountId())) { currentStream.setScopeType(null); } /*if (currentStream.getScopeType() != null) { getEmailContactLink.setHref("/resources/emailcontact/stream/person/" + person.getId()); getEmailContactLink.setVisible(true); }*/ if (!singleActivityMode) { EventBus.getInstance().notifyObservers(new PostableStreamScopeChangeEvent(currentStream)); } } }); EventBus.getInstance().addObserver(GotGroupModelViewInformationResponseEvent.class, new Observer<GotGroupModelViewInformationResponseEvent>() { public void update(final GotGroupModelViewInformationResponseEvent event) { onGroupModelViewReceived(event.getResponse()); } }); } /** * Processing when group information is received. * * @param group * The group. */ private void onGroupModelViewReceived(final DomainGroupModelView group) { // If group is null, then that means that the group // was not found. As a result, a "Group not found" // page should be displayed. // This page is very similar to the "Activity not found" page if (group == null) { showGroupNotFoundPage(); } else { currentDisplayName = group.getDisplayName(); currentScopeId = group.getStreamId(); currentStream.setDisplayName(group.getName()); streamDetailsComposite.setVisible(true); if (group.isRestricted()) { streamOptionsPanel.getStyle().setDisplay(Display.NONE); currentStream.setScopeType(null); postBox.setVisible(false); errorPanel.clear(); errorPanel.setVisible(true); activitySpinner.addClassName(StaticResourceBundle.INSTANCE.coreCss().displayNone()); errorPanel.add(new Label("Access to this group is restricted")); errorPanel.add(new Label("To view this group's stream please request access from its coordinator")); final SpinnerLabelButton button = new SpinnerLabelButton(new ClickHandler() { public void onClick(final ClickEvent inArg0) { GroupMembershipRequestModel.getInstance().insert(group.getShortName()); } }); EventBus.getInstance().addObserver(InsertedRequestForGroupMembershipResponseEvent.class, new Observer<InsertedRequestForGroupMembershipResponseEvent>() { public void update(final InsertedRequestForGroupMembershipResponseEvent inArg1) { button.disable(); EventBus.getInstance() .notifyObservers( new ShowNotificationEvent(new Notification( "Your request for access has been sent"))); } }); button.addStyleName(StaticResourceBundle.INSTANCE.coreCss().requestAccessButton()); errorPanel.add(button); streamPanel.clear(); unseenActivityNotificationPanel.setActive(true); } else { currentStreamEntity = group; if (group.getStickyActivity() != null && !singleActivityMode && (loadedSearchTerm == null || loadedSearchTerm == "")) { stickyActivityHolder.add(stickyActivityRenderer.render(group.getStickyActivity())); UIObject.setVisible(stickyActivityArea, true); } } boolean isCoordinator = false; for (PersonModelView coordinator : group.getCoordinators()) { AvatarBadgeManager.getInstance().setBadge(style.streamContainerPanel(), coordinator.getUniqueId()); if (coordinator.getAccountId().equals(Session.getInstance().getCurrentPerson().getAccountId())) { isCoordinator = true; } } if (!group.isStreamPostable() && !isCoordinator) { currentStream.setScopeType(null); } /*else { getEmailContactLink.setHref("/resources/emailcontact/stream/group/" + group.getId()); getEmailContactLink.setVisible(true); }*/ if (!singleActivityMode) { if (Session.getInstance().getCurrentPersonRoles().contains(Role.SYSTEM_ADMIN) || isCoordinator) { streamContainerPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().hasOwnerRights()); } EventBus.getInstance().notifyObservers(new PostableStreamScopeChangeEvent(currentStream)); } if (deferLoadAwaitingEntityReceived) { deferLoadAwaitingEntityReceived = false; currentRequestObj = StreamJsonRequestFactory.setExcludeId(group.getStickyActivityId(), currentRequestObj); if (!deferLoadAwaitingQueryBuilt) { fetchStream(currentRequestObj); } } } } /** * Shows a "not found" message. */ private void showGroupNotFoundPage() { activitySpinner.addClassName(StaticResourceBundle.INSTANCE.coreCss().displayNone()); streamPanel.clear(); errorPanel.clear(); postBox.setVisible(false); Panel errorReport = new FlowPanel(); errorReport.addStyleName(StaticResourceBundle.INSTANCE.coreCss().warningReport()); FlowPanel centeringPanel = new FlowPanel(); centeringPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().warningReportContainer()); centeringPanel.add(errorReport); streamPanel.add(centeringPanel); FlowPanel msgPanel = new FlowPanel(); Label msgHeader = new Label("Group not found"); msgHeader.addStyleName(StaticResourceBundle.INSTANCE.coreCss().warningMessage()); Label msgText = new Label("The group you were looking for has been deleted or could not be found."); FlowPanel text = new FlowPanel(); text.add(msgText); text.addStyleName(StaticResourceBundle.INSTANCE.coreCss().errorMessageText()); msgPanel.add(msgHeader); msgPanel.add(msgText); streamPanel.removeStyleName(StaticResourceBundle.INSTANCE.coreCss().hidden()); streamPanel.setVisible(true); streamContainerPanel.setVisible(true); errorReport.add(msgPanel); errorPanel.setVisible(true); errorReport.setVisible(true); centeringPanel.setVisible(true); msgPanel.setVisible(true); } /** * Handle views changed. * * @param inViews * the views. */ protected void handleViewsChanged(final List<String> inViews) { String search = Session.getInstance().getParameterValue("search"); // prevent reloading the same content if (!loadedViews.equals(inViews) || !loadedSearchTerm.equals(search)) { loadStream(inViews, search); } List<String> views = new ArrayList<String>(inViews); if (views.size() < 2 || !"sort".equals(views.get(views.size() - 2))) { views.add("sort"); views.add("recent"); } Map<String, String> params = (search == null || search.isEmpty()) ? Collections.EMPTY_MAP : Collections .singletonMap("search", search); views.set(views.size() - 1, "recent"); recentSort.setTargetHistoryToken(Session.getInstance().generateUrl( new CreateUrlRequest(Page.ACTIVITY, views, params))); views.set(views.size() - 1, "popular"); popularSort.setTargetHistoryToken(Session.getInstance().generateUrl( new CreateUrlRequest(Page.ACTIVITY, views, params))); views.set(views.size() - 1, "active"); activeSort.setTargetHistoryToken(Session.getInstance().generateUrl( new CreateUrlRequest(Page.ACTIVITY, views, params))); } /** * Setup bookmarks and custom streams. */ private void setupStreamsAndBookmarks() { final EventBus eventBus = EventBus.getInstance(); eventBus.addObserver(GotCurrentUserStreamBookmarks.class, new Observer<GotCurrentUserStreamBookmarks>() { private final AvatarUrlGenerator groupUrlGen = new AvatarUrlGenerator(EntityType.GROUP); private final AvatarUrlGenerator personUrlGen = new AvatarUrlGenerator(EntityType.PERSON); public void update(final GotCurrentUserStreamBookmarks event) { bookmarkList.clear(); bookmarksWidgetMap.clear(); List<StreamFilter> sortedStreamFilters = event.getResponse(); Collections.sort(sortedStreamFilters, new StreamFilterNameComparator()); for (final StreamFilter filter : sortedStreamFilters) { JSONObject req = StreamJsonRequestFactory.getJSONRequest(filter.getRequest()); String uniqueId = null; String entityType = null; String imgUrl = ""; if (req.containsKey("query")) { JSONObject query = req.get("query").isObject(); if (query.containsKey(StreamJsonRequestFactory.RECIPIENT_KEY)) { JSONArray recipient = query.get(StreamJsonRequestFactory.RECIPIENT_KEY).isArray(); if (recipient.size() > 0) { JSONObject recipientObj = recipient.get(0).isObject(); uniqueId = recipientObj.get("name").isString().stringValue(); entityType = recipientObj.get("type").isString().stringValue().toLowerCase(); AvatarUrlGenerator urlGen = groupUrlGen; if ("person".equals(entityType)) { urlGen = personUrlGen; } imgUrl = urlGen.getSmallAvatarUrl(filter.getOwnerAvatarId()); } } } if (uniqueId != null && entityType != null) { String bookmarkUrl = entityType + "/" + uniqueId; StreamNamePanel bookmarkFilter = createPanel(filter.getName(), bookmarkUrl, imgUrl, new ClickHandler() { public void onClick(final ClickEvent event) { if (new WidgetJSNIFacadeImpl() .confirm("Are you sure you want to delete this bookmark?")) { StreamBookmarksModel.getInstance().delete(filter.getId()); } event.stopPropagation(); } }, style.deleteBookmark(), "", true); bookmarkList.add(bookmarkFilter); bookmarksWidgetMap.put(bookmarkUrl, bookmarkFilter); } } if (sortedStreamFilters.size() == 0) { Label defaultLabel = new Label("Bookmarks allow you to quickly jump to any stream in Eureka."); defaultLabel.addStyleName(style.noBookmarksMessage()); bookmarkList.add(defaultLabel); } bookmarksLoaded = true; checkInit(); } }); eventBus.addObserver(StreamActivitySubscriptionChangedEvent.class, new Observer<StreamActivitySubscriptionChangedEvent>() { public void update(final StreamActivitySubscriptionChangedEvent ev) { boolean newStatus = ev.getResponse().getReceiveNewActivityNotifications(); setSubscribeStatus(newStatus); String msg = newStatus ? "You will now receive emails for new activities to this stream" : "You will no longer receive emails for new activities to this stream"; eventBus.notifyObservers(new ShowNotificationEvent(new Notification(msg))); } }); eventBus.addObserver(GotStreamActivitySubscriptionResponseEvent.class, new Observer<GotStreamActivitySubscriptionResponseEvent>() { public void update(final GotStreamActivitySubscriptionResponseEvent result) { setSubscribeStatus(result.isSubscribed()); } }); eventBus.addObserver(GotCurrentUserCustomStreamsResponseEvent.class, new Observer<GotCurrentUserCustomStreamsResponseEvent>() { public void update(final GotCurrentUserCustomStreamsResponseEvent event) { filterList.clear(); customStreamWidgetMap.clear(); StreamNamePanel savedBy = createPanel("My Saved Items", "custom/0/" + "{\"query\":{\"savedBy\":\"" + Session.getInstance().getCurrentPerson().getAccountId() + "\"}}", "style/images/customStream.png", null, "", "", false); filterList.add(savedBy); customStreamWidgetMap.put(0L, savedBy); StreamNamePanel likedBy = createPanel("My Liked Items", "custom/1/" + "{\"query\":{\"likedBy\":[{\"type\":\"PERSON\", \"name\":\"" + Session.getInstance().getCurrentPerson().getAccountId() + "\"}]}}/My Liked Items", "style/images/customStream.png", null, "", "", false); filterList.add(likedBy); customStreamWidgetMap.put(1L, likedBy); for (final StreamFilter filter : event.getResponse().getStreamFilters()) { StreamNamePanel filterPanel = createPanel( filter.getName(), "custom/" + filter.getId() + "/" + URL.encodeComponent(filter.getRequest(). replace("%%CURRENT_USER_ACCOUNT_ID%%", Session.getInstance().getCurrentPerson().getAccountId())), "style/images/customStream.png", new ClickHandler() { public void onClick(final ClickEvent event) { Dialog.showCentered(new CustomStreamDialogContent((Stream) filter)); event.stopPropagation(); } }, style.editCustomStream(), "edit", false); filterList.add(filterPanel); customStreamWidgetMap.put(filter.getId(), filterPanel); } customStreamsLoaded = true; checkInit(); } }); eventBus.addObserver(StreamSearchBeginEvent.class, new Observer<StreamSearchBeginEvent>() { public void update(final StreamSearchBeginEvent event) { if (null == event.getSearchText()) { eventBus.notifyObservers(new UpdateHistoryEvent(new CreateUrlRequest("search", "", false))); searchBox.setText(""); } } }); } /** * Add events. */ private void addEventHandlers() { moreLink.addClickHandler(new ClickHandler() { public void onClick(final ClickEvent event) { moreSpinner.removeClassName(StaticResourceBundle.INSTANCE.coreCss().displayNone()); JSONObject moreItemsRequest = StreamJsonRequestFactory.setMaxId(longOldestActivityId, StreamJsonRequestFactory.getJSONRequest(currentRequestObj.toString())); fetchStream(moreItemsRequest); } }); searchBox.addKeyUpHandler(new KeyUpHandler() { private int lastSearchLength = 0; public void onKeyUp(final KeyUpEvent event) { final String searchText = searchBox.getText(); final int searchTextLength = searchText.length(); if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { lastSearchLength = searchTextLength; searchTimer.cancel(); searchUrlTimer.cancel(); // don't load stream here - the URL change will cause it to be reloaded EventBus.getInstance().notifyObservers( new UpdateHistoryEvent(new CreateUrlRequest("search", searchText, false))); } else if ((searchTextLength > 2 && searchTextLength != lastSearchLength) || searchTextLength < lastSearchLength) { lastSearchLength = searchTextLength; searchTimer.schedule(SEARCH_UPDATE_DELAY); } } }); searchBox.addBlurHandler(new BlurHandler() { public void onBlur(final BlurEvent inEvent) { updateUrlWithSearchTerm(); } }); addBookmark.addClickHandler(new ClickHandler() { public void onClick(final ClickEvent event) { StreamBookmarksModel.getInstance().insert(currentScopeId); addBookmark.setVisible(false); EventBus.getInstance().notifyObservers( new ShowNotificationEvent(new Notification("You have bookmarked this stream."))); } }); subscribeViaEmail.addClickHandler(new ClickHandler() { public void onClick(final ClickEvent event) { if (!isSubscribed) { if (currentStream.getScopeType().equals(ScopeType.GROUP)) { Dialog.showCentered(new GroupEmailSubscribeOptionsDialogContent(currentStream.getUniqueKey())); } else if (currentStream.getScopeType().equals(ScopeType.PERSON)) { PersonActivitySubscriptionModel.getInstance().insert(currentStream.getUniqueKey()); setSubscribeStatus(true); } } else { Deletable<String> deletable = null; if (currentStream.getScopeType().equals(ScopeType.GROUP)) { deletable = GroupActivitySubscriptionModel.getInstance(); } else if (currentStream.getScopeType().equals(ScopeType.PERSON)) { deletable = PersonActivitySubscriptionModel.getInstance(); } if (deletable != null) { deletable.delete(currentStream.getUniqueKey()); setSubscribeStatus(false); } } } }); addToStartPage.addClickHandler(new ClickHandler() { public void onClick(final ClickEvent event) { // For the app's location, use the current URL minus a few parameters we know we don't want. (They are // used by other lists, but get left in the URL when switching tabs.) // We don't build the URL from the stream id, since that doesn't take search terms into account. HashMap<String, String> params = new HashMap<String, String>(); params.put("listId", null); params.put("listFilter", null); params.put("listSort", null); params.put("startIndex", null); params.put("endIndex", null); String url = Session.getInstance().generateUrl(new CreateUrlRequest(params)); // make a version of the query that doesn't have the exclusion list JSONObject request = currentRequestObj; if (request.containsKey("exclude")) { request = new JSONObject(); for (String key : currentRequestObj.keySet()) { if (!"exclude".equals(key)) { request.put(key, currentRequestObj.get(key)); } } } // TODO: get correct title from somewhere. String prefs = "{\"streamQuery\":" + makeJsonString(STREAM_URL_TRANSFORMER.getUrl(null, request.toString())) + ",\"gadgetTitle\":" + makeJsonString(currentDisplayName) + ",\"streamLocation\":" + makeJsonString(url) + "}"; GadgetModel.getInstance().insert( new AddGadgetToStartPageRequest("{d7a58391-5375-4c76-b5fc-a431c42a7555}", null, prefs)); EventBus.getInstance() .notifyObservers( new ShowNotificationEvent(new Notification( "This stream will now show up on your start page."))); } }); createFilter.addClickHandler(new ClickHandler() { public void onClick(final ClickEvent event) { Dialog.showCentered(new CustomStreamDialogContent()); } }); feedLink.addClickHandler(new ClickHandler() { public void onClick(final ClickEvent event) { Window.Location.assign("/resources/atom/stream/query/recipient/" + currentStream.getScopeType() + ":" + currentStream.getUniqueKey()); } }); } /** * Requests a stream via the model and tracks it for proper reciept matching. * * @param request * The request in JSON form. */ private void fetchStream(final JSONObject request) { currentStreamRequest = request.toString(); StreamModel.getInstance().fetch(currentStreamRequest, false); } /** * Updates the URL to include the search term. */ private void updateUrlWithSearchTerm() { String searchText = searchBox.getText(); String searchParam = Session.getInstance().getParameterValue("search"); if (!searchText.equals(searchParam)) { EventBus.getInstance().notifyObservers( new UpdateHistoryEvent(new CreateUrlRequest("search", searchText, false))); } } /** * Update subscription status consistently. * * @param inIsSubscribed * New status. */ private void setSubscribeStatus(final boolean inIsSubscribed) { isSubscribed = inIsSubscribed; subscribeViaEmail.setText(isSubscribed ? "Unsubscribe to Emails" : "Subscribe via Email"); } /** * Creates the JSON representation of a string value. (Escapes characters and adds string delimiters or returns null * keyword as applicable.) See http://www.json.org/ for syntax. Assumes the string contains no control characters. * * @param input * Input string, possibly null. * @return JSON string representation. */ private static native String makeJsonString(final String input) /*-{ return input == null ? 'null' : '"' + input.replace(/\\/g,'\\\\').replace(/"/g,'\\"') + '"'; }-*/; /** * Append a new message. * * @param message * the messa.ge */ private void appendActivity(final ActivityDTO message) { Panel newActivity = renderer.render(message); newActivity.setVisible(false); streamPanel.insert(newActivity, 0); EffectsFacade.nativeFadeIn(newActivity.getElement(), true); } /** * Load a stream. * * @param views * the stream history link. * @param searchTerm * the search term. */ private void loadStream(final List<String> views, final String searchTerm) { // save for change detection loadedViews = new ArrayList<String>(views); loadedSearchTerm = searchTerm; Window.scrollTo(0, 0); noResults.addClassName(StaticResourceBundle.INSTANCE.coreCss().displayNone()); Session.getInstance().getActionProcessor().setQueueRequests(true); addBookmark.setVisible(false); subscribeViaEmail.setVisible(false); feedLink.setVisible(false); streamOptionsPanel.getStyle().setDisplay(Display.BLOCK); streamDetailsComposite.init(); errorPanel.clear(); errorPanel.setVisible(false); AvatarBadgeManager.getInstance().clearBadges(); singleActivityMode = false; activitySpinner.removeClassName(StaticResourceBundle.INSTANCE.coreCss().displayNone()); moreLink.setVisible(false); streamPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().hidden()); currentRequestObj = StreamJsonRequestFactory.getEmptyRequest(); currentStream = new StreamScope(ScopeType.PERSON, Session.getInstance().getCurrentPerson().getAccountId()); ShowRecipient showRecipient = ShowRecipient.YES; streamContainerPanel.removeStyleName(StaticResourceBundle.INSTANCE.coreCss().hasOwnerRights()); stickyActivityHolder.clear(); UIObject.setVisible(stickyActivityArea, false); renderer.setShowStickActivity(false); currentStreamEntity = null; deferLoadAwaitingQueryBuilt = false; deferLoadAwaitingEntityReceived = false; //getEmailContactLink.setVisible(false); boolean streamIsAnEntity = false; if (views == null || views.size() == 0 || views.get(0).equals("following") || ((views.get(0).equals("sort") && (views.size() == 2)))) { currentRequestObj = StreamJsonRequestFactory.setSourceAsFollowing(currentRequestObj); setAsActiveStream(followingFilterPanel); EventBus.getInstance().notifyObservers(new PostableStreamScopeChangeEvent(currentStream)); feedLink.setVisible(true); streamDetailsComposite.setStreamTitle("Following", CustomAvatar.FOLLOWING); streamDetailsComposite.setCondensedMode(true); currentDisplayName = "Following"; } else if (views.get(0).equals("person") && views.size() >= 2) { streamIsAnEntity = true; showRecipient = ShowRecipient.RESOURCE_ONLY; String accountId = views.get(1); currentRequestObj = StreamJsonRequestFactory.addRecipient(EntityType.PERSON, accountId, currentRequestObj); PersonalInformationModel.getInstance().fetch(accountId, false); currentStream.setScopeType(ScopeType.PERSON); currentStream.setUniqueKey(accountId); String mapKey = "person/" + accountId; setAsActiveStream(bookmarksWidgetMap.get(mapKey)); if (!bookmarksWidgetMap.containsKey(mapKey)) { addBookmark.setVisible(true); } else { addBookmark.setVisible(false); currentDisplayName = bookmarksWidgetMap.get(mapKey).getStreamName(); } subscribeViaEmail.setVisible(true); feedLink.setVisible(true); streamDetailsComposite.setCondensedMode(false); PersonActivitySubscriptionModel.getInstance().fetch(currentStream.getUniqueKey(), true); } else if (views.get(0).equals("group") && views.size() >= 2) { streamIsAnEntity = true; showRecipient = ShowRecipient.RESOURCE_ONLY; String shortName = views.get(1); currentRequestObj = StreamJsonRequestFactory.addRecipient(EntityType.GROUP, shortName, currentRequestObj); GroupModel.getInstance().fetch(shortName, false); currentStream.setScopeType(ScopeType.GROUP); currentStream.setUniqueKey(shortName); String mapKey = "group/" + shortName; setAsActiveStream(bookmarksWidgetMap.get(mapKey)); if (!bookmarksWidgetMap.containsKey(mapKey)) { addBookmark.setVisible(true); } else { addBookmark.setVisible(false); currentDisplayName = bookmarksWidgetMap.get(mapKey).getStreamName(); } subscribeViaEmail.setVisible(true); feedLink.setVisible(true); streamDetailsComposite.setCondensedMode(false); // Note: the links this will generate will only be visible if user is an admin/coordinator (via CSS) renderer.setShowStickActivity(true); deferLoadAwaitingEntityReceived = true; deferLoadAwaitingQueryBuilt = true; GroupActivitySubscriptionModel.getInstance().fetch(currentStream.getUniqueKey(), true); } else if (views.get(0).equals("custom") && views.size() >= 3) { currentRequestObj = StreamJsonRequestFactory.getJSONRequest(URL.decodeComponent(views.get(2))); setAsActiveStream(customStreamWidgetMap.get(Long.parseLong(views.get(1)))); currentStream.setScopeType(null); EventBus.getInstance().notifyObservers(new PostableStreamScopeChangeEvent(currentStream)); feedLink.setVisible(true); String streamName = customStreamWidgetMap.get(Long.parseLong(views.get(1))).getStreamName(); streamDetailsComposite.setStreamTitle(streamName, CustomAvatar.FOLLOWING); streamDetailsComposite.setCondensedMode(true); currentDisplayName = streamName; } else if (views.get(0).equals("everyone")) { currentRequestObj = StreamJsonRequestFactory.getEmptyRequest(); setAsActiveStream(everyoneFilterPanel); EventBus.getInstance().notifyObservers(new PostableStreamScopeChangeEvent(currentStream)); feedLink.setVisible(true); streamDetailsComposite.setStreamTitle("Everyone", CustomAvatar.EVERYONE); streamDetailsComposite.setCondensedMode(true); currentDisplayName = "Everyone"; } else if (views.size() == 1) { showRecipient = ShowRecipient.RESOURCE_ONLY; singleActivityMode = true; } if (searchTerm != null && searchTerm.length() > 0) { streamSearchStatusWidget.setSearchTerm(searchTerm); currentRequestObj = StreamJsonRequestFactory.setSearchTerm(searchTerm, currentRequestObj); searchContainer.addClassName(style.activeSearch()); searchBox.setText(searchTerm); } else { streamSearchStatusWidget.onSearchCanceled(); searchContainer.removeClassName(style.activeSearch()); } if (!streamIsAnEntity) { streamDetailsComposite.setVisible(true); } renderer.setShowRecipientInStream(showRecipient); if (!singleActivityMode) { streamOptionsPanel.getStyle().setDisplay(Display.BLOCK); String sortBy = "recent"; if (views != null && views.size() >= 2 && "sort".equals(views.get(views.size() - 2))) { sortBy = views.get(views.size() - 1); } recentSort.removeStyleName(style.activeSort()); popularSort.removeStyleName(style.activeSort()); activeSort.removeStyleName(style.activeSort()); sortKeyword = "date"; if ("recent".equals(sortBy)) { recentSort.addStyleName(style.activeSort()); sortKeyword = "date"; } else if ("popular".equals(sortBy)) { popularSort.addStyleName(style.activeSort()); sortKeyword = "interesting"; } else if ("active".equals(sortBy)) { activeSort.addStyleName(style.activeSort()); sortKeyword = "commentdate"; } currentRequestObj = StreamJsonRequestFactory.setSort(sortKeyword, currentRequestObj); // see notes where field declared deferLoadAwaitingQueryBuilt = false; if (!deferLoadAwaitingEntityReceived) { fetchStream(currentRequestObj); } } else { streamDetailsComposite.setCondensedMode(false); streamOptionsPanel.getStyle().setDisplay(Display.NONE); postBox.setVisible(false); try { ActivityModel.getInstance().fetch(Long.parseLong(views.get(0)), true); } catch (Exception e) { // Do nothing. int x = 0; } } Session.getInstance().getActionProcessor().fireQueuedRequests(); Session.getInstance().getActionProcessor().setQueueRequests(false); } /** * Set a stream as active. * * @param panel * the panel. */ private void setAsActiveStream(final Panel panel) { Scheduler.get().scheduleDeferred(new ScheduledCommand() { public void execute() { if (currentlyActiveStream != null) { currentlyActiveStream.removeStyleName(style.activeStream()); } if (panel != null) { currentlyActiveStream = panel; panel.addStyleName(style.activeStream()); } } }); } /** * Check if we should init. */ private void checkInit() { if (bookmarksLoaded && customStreamsLoaded && !hasInited) { hasInited = true; handleViewsChanged(Session.getInstance().getUrlViews()); } } /** * Create LI Element for stream lists. * * @param name * the name of the item. * @param view * the history token to load. * @param modifyClickHandler * click handler for modify. * @param modifyClass * the class for the modify button. * @param modifyText * the text for the modify button. * @param imgUrl * the img url. * @param isAvatar * if the image is an avatar. * @return the LI. */ private StreamNamePanel createPanel(final String name, final String view, final String imgUrl, final ClickHandler modifyClickHandler, final String modifyClass, final String modifyText, final boolean isAvatar) { StreamNamePanel panel = new StreamNamePanel(name); panel.addStyleName(style.streamOptionChild()); panel.addClickHandler(new ClickHandler() { public void onClick(final ClickEvent event) { History.newItem(Session.getInstance().generateUrl(new CreateUrlRequest(Page.ACTIVITY, view))); } }); FlowPanel innerPanel = new FlowPanel(); Image streamImage = new Image(imgUrl); if (isAvatar) { streamImage.addStyleName(style.smallAvatar()); } innerPanel.add(streamImage); Label streamName = new Label(name); streamName.setTitle(name); streamName.addStyleName(style.streamName()); streamName.addStyleName(StaticResourceBundle.INSTANCE.coreCss().ellipsis()); innerPanel.add(streamName); if (modifyClickHandler != null) { Label modifyLink = new Label(modifyText); modifyLink.addStyleName(modifyClass); modifyLink.addClickHandler(modifyClickHandler); innerPanel.add(modifyLink); } panel.add(innerPanel); return panel; } /** * Binder for building UI. */ interface LocalUiBinder extends UiBinder<Widget, ActivityContent> { } }